package ch.ifage.business.dom;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Model of a step of a workflow.
 *
 * @author Christian Burri
 *
 */
public class Step implements Serializable {

	/**
	 * Le numéro de série.
	 */
	private static final long serialVersionUID = -7617084984708988687L;

	/**
	 * Identifiant unique de l'étape.
	 */
	private StepIdentity identity;
	
	/**
	 * Les propriétés de l'étape.
	 */
	private StepProperties properties;

	/**
	 * job père, null si c'est le premier step.
	 */
	private Step father; 
	
	/**
	 * Liste des jobs fils.
	 */
	private List<Step> listOfChild;

	/**
	 * @return the father
	 */
	public final Step getFather() {
		return father;
	}

	/**
	 * @param father the father to set
	 */
	public final void setFather(final Step father) {
		this.father = father;
	}

	/**
	 * @return the listOfChild
	 */
	public final List<Step> getListOfChild() {
		return listOfChild;
	}

	/**
	 * @param listOfChild the listOfChild to set
	 */
	public final void setListOfChild(final List<Step> listOfChild) {
		this.listOfChild = listOfChild;
	}

	/**
	 * @return the identity
	 */
	public final StepIdentity getIdentity() {
		return identity;
	}

	/**
	 * @param identity the identity to set
	 */
	public final void setIdentity(final StepIdentity identity) {
		this.identity = identity;
	}

	/**
	 * @return the properties
	 */
	public final StepProperties getProperties() {
		return properties;
	}

	/**
	 * @param properties the properties to set
	 */
	public final void setProperties(final StepProperties properties) {
		this.properties = properties;
	}

	/**
	 * constructeur pour l'héritage.
	 * Ne fait rien.
	 */
	protected Step() {
		super();
		this.identity = null;
		this.properties = null;
		this.father = null;
		this.listOfChild = new ArrayList<Step>();
	}

	
	/**
	 * Contructueur sans les fils.
	 * @param identity identité de l'étape.
	 * @param properties caractéristiques de l'étape.
	 * @param father père de l'étape.
	 */
	public Step(final StepIdentity identity, final StepProperties properties, final Step father) {
		super();
		this.identity = identity;
		this.properties = properties;
		this.father = father;
		this.listOfChild = new ArrayList<Step>();
		father.addChildStep(this);
	}
	
	/**
	 * Contructueur sans les fils, ni père.
	 * @param identity identité de l'étape.
	 * @param properties caractéristiques de l'étape.
	 */
	public Step(final StepIdentity identity, final StepProperties properties) {
		super();
		this.identity = identity;
		this.properties = properties;
		this.father = null;
		this.listOfChild = new ArrayList<Step>();
	}

	
	/**
	 * Ajout d'une étape fils.
	 * @param child étape fils.
	 */
	public final void addChildStep(final Step child) {
			this.listOfChild.add(child);
	}
	
	/**
	 * Indique si une chaîne de cractères se trouve dans les log des descendants.
	 * @param subStringOfLog sous chaîne à rechercher dans la log.
	 * @return booléen indiquant la présence de la chaîne.
	 */
	public boolean logContainsSubString(final String subStringOfLog) {
		boolean result = this.getProperties().getLog().toLowerCase().contains(subStringOfLog);
		if (result) {
			return result;
		} else {
			Integer childIndex = this.getListOfChild().size();
			while (!result && (childIndex > 0)) {
				childIndex -= 1;
				result = this.getListOfChild().get(childIndex).logContainsSubString(subStringOfLog);
			}
			return result;
		}
	}
	
	
	/** 
	 * List of children uid.
	 * @return string
	 */
	private String listOfChildToString() {
		String string = "";
		if (listOfChild.size() == 0) {
			string = "no child";
		} else {
			for (Iterator<Step> iterator = listOfChild.iterator(); iterator.hasNext();) {
				string = string + iterator.next().toString(); 
			}
		}
		return string;
	}
	

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public final String toString() {
		Integer uidFather;
		if (this.father == null) {
			uidFather = 0;
		} else {
			if (this.father.properties == null) {
				uidFather = 0;
			} else {
				uidFather = this.father.identity.getUid();
			}	
		}
		
		String id;
		if (this.identity == null) {
			id = "no identity";
		} else {
			id =  this.identity.toString();
		}
		
		String pr;
		if (this.properties == null) {
			pr = "no properties";
		} else {
			pr =  this.properties.toString();
		}
			
		return "Step [ Identity:" +  id + "\n" 
			 + "       Poperties: " + pr + "\n"
		     + "       Father: " + uidFather + "\n"
			 + "       Children: " + listOfChildToString() 
			 + "     ]\n";
	}
	
	
	
}
